#include "Board.h"


Board::Board(void)
{
}


Board::~Board(void)
{
}

Board::Board(PlayerControl white_player, PlayerControl black_player, float cellSize, unsigned int txId, float delta_t, float v){//, bool timer, int maximum_time){
	this->white_player = white_player;
	this->black_player = black_player;
	this->turn = WHITE;
	this->white_n_checkers = this->black_n_checkers = 12;

	glQ = gluNewQuadric();
	for(unsigned int i = 0; i < 8; ++i)
		for(unsigned int j = 0; j < 8; ++j){

			if(i%2 == j%2)
				cells[i][j].player = INVALID;
			else
				cells[i][j].player = NONE;

			cells[i][j].nCheckers = 0;
			cells[i][j].x = j;
			cells[i][j].y = i;
		}

	this->cellSize = cellSize;
	this->txId = txId;

	this->size = 4*cellSize;

	cells[7][4].player = WHITE;
	cells[7][4].nCheckers = 12;

	cells[0][3].player = BLACK;
	cells[0][3].nCheckers = 12;
	checkerHeight = .5;
	checkerRadius = cellSize/2.0;

	application_status = INITIAL;

	this->delta_t = delta_t;
	this->v = v;

	game_film_turn = 0;

	this->timer = false;

	camera_white = Camera(0,20,20);
	camera_black = Camera(0,20,-20);
	camera_black_white = Camera(-20,20,0);
	camera_white_black = Camera(20,20,0);
	current_cam = FREE;
	ani_camera_status = NOT_ANIMATE;

	white_board_ncheckers = black_board_ncheckers = 0;
	white_board_z = size + 2*cellSize;
	black_board_z = -white_board_z;

	white_material.ambient[0] = 0.6;
	white_material.ambient[1] = 0.6;
	white_material.ambient[2] = 0.6;
	white_material.ambient[3] = 1.0;

	white_material.diffuse[0] = 1.0;
	white_material.diffuse[1] = 1.0;
	white_material.diffuse[2] = 1.0;
	white_material.diffuse[3] = 1.0;

	white_material.specular[0] = 0.5;
	white_material.specular[1] = 0.5;
	white_material.specular[2] = 0.5;
	white_material.specular[3] = 1.0;
	
	white_material.shininess[0] = 8.0;

	black_material.ambient[0] = 0.6;
	black_material.ambient[1] = 0.0;
	black_material.ambient[2] = 0.0;
	black_material.ambient[3] = 1.0;

	black_material.diffuse[0] = 1.0;
	black_material.diffuse[1] = 0.0;
	black_material.diffuse[2] = 0.0;
	black_material.diffuse[3] = 1.0;

	black_material.specular[0] = 0.5;
	black_material.specular[1] = 0.0;
	black_material.specular[2] = 0.0;
	black_material.specular[3] = 1.0;
	
	black_material.shininess[0] = 8.0;

	board_material.ambient[0] = 0.6;
	board_material.ambient[1] = 0.6;
	board_material.ambient[2] = 0.6;
	board_material.ambient[3] = 1.0;

	board_material.diffuse[0] = 0.8;
	board_material.diffuse[1] = 0.8;
	board_material.diffuse[2] = 0.8;
	board_material.diffuse[3] = 0.8;

	board_material.specular[0] = 0.4;
	board_material.specular[1] = 0.4;
	board_material.specular[2] = 0.4;
	board_material.specular[3] = 1.0;
	
	board_material.shininess[0] = 1.0;

	selected_material.ambient[0] = 0.0;
	selected_material.ambient[1] = 0.6;
	selected_material.ambient[2] = 0.0;
	selected_material.ambient[3] = 1.0;

	selected_material.diffuse[0] = 0.0;
	selected_material.diffuse[1] = 1.0;
	selected_material.diffuse[2] = 0.0;
	selected_material.diffuse[3] = 1.0;

	selected_material.specular[0] = 0.0;
	selected_material.specular[1] = 0.6;
	selected_material.specular[2] = 0.0;
	selected_material.specular[3] = 1.0;
	
	selected_material.shininess[0] = 20.0;
}

string Board::toString(){
	stringstream ss;
	ss << '[';
	for(int i = 0; i<8 ; ++i){
		ss << '[';
		for(int j = 0; j<8; ++j){
			switch(cells[i][j].player){
				case NONE:
					ss << '-';
					break;
				case INVALID:
					ss << 'x';
					break;
				case WHITE:
					ss << "w-" << cells[i][j].nCheckers;
					break;
				case BLACK:
					ss << "b-" << cells[i][j].nCheckers;
					break;
			}
			if(j != 7)
				ss << ',';
			else
				ss << ']';
		}
		if(i != 7)
			ss << ',';
		else
			ss << ']';
	}
	return ss.str();
}

PlayerControl Board::getCurrentPlayerControl(){
	switch(turn){
		case WHITE:
			return white_player;
		case BLACK:
			return black_player;
	}
}

void Board::setValidMoves(vector<Move> moves){
	selected.clear();

	for(unsigned int i = 0; i< moves.size(); ++i ){
		valid_moves[moves[i].xf*100 + moves[i].yf] = moves[i];
		selected.push_back(pair<int,int>(moves[i].xf,moves[i].yf));
	}
}

void Board::drawBoard(GLenum mode){
	if(mode == GL_RENDER){
		drawBoardStacks();

		if(game_status == ANIMATION)
			drawAnimation();

		board_material.applyMaterial();

		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, txId);
	
		glBegin(GL_POLYGON);
			glNormal3f(0,1,0);
			glTexCoord2f(0.0,0.0); glVertex3f(-size,0.0,size);
			glTexCoord2f(1.0,0.0); glVertex3f(size,0.0,size);
			glTexCoord2f(1.0,1.0); glVertex3f(size,0.0,-size);
			glTexCoord2f(0.0,1.0); glVertex3f(-size,0.0,-size);
		glEnd();

		glDisable(GL_TEXTURE_2D);

		float temp = cellSize/2.0;

		glPushMatrix();
		glTranslatef(0,0,white_board_z);
		glBegin(GL_POLYGON);
			glNormal3f(0,1,0);
			glVertex3f(-temp,0,temp);
			glVertex3f(temp,0,temp);
			glVertex3f(temp,0,-temp);
			glVertex3f(-temp,0,-temp);
		glEnd();
		glPopMatrix();

		glPushMatrix();
		glTranslatef(0,0,black_board_z);
		glBegin(GL_POLYGON);
			glNormal3f(0,1,0);
			glVertex3f(-temp,0,temp);
			glVertex3f(temp,0,temp);
			glVertex3f(temp,0,-temp);
			glVertex3f(-temp,0,-temp);
		glEnd();
		glPopMatrix();
	}
}

void Board::drawChecker(PlayerType player){

	switch(player){
		case WHITE:
			white_material.applyMaterial();
			break;
		case BLACK:
			black_material.applyMaterial();
			break;
	}
	
	glPushMatrix();
	glRotatef(-90.0,1,0,0);
	gluCylinder(glQ, checkerRadius, checkerRadius, checkerHeight-.05, 20, 20);
	
	glPushMatrix();
	glTranslatef(0,0,checkerHeight -.05);
	gluDisk (glQ, 0.0, checkerRadius,20,20);
	glPopMatrix();

	glPopMatrix();
}

void Board::drawCheckerStack(PlayerType player, int n_checkers){
	for(int i = 0; i < n_checkers; ++i){
		glPushMatrix();
		glTranslatef(0.0, i*checkerHeight,0.0);
		drawChecker(player);
		glPopMatrix();
	}
};

void Board::drawBoardStacks(){
	BoardCell* cell;
	for(unsigned int y = 0; y < 8; ++y)
		for(unsigned int x = 0; x < 8; ++x)
			if((cell = &cells[y][x])->player != NONE){

				glPushMatrix();
				glTranslatef(-size + x*cellSize + cellSize/2.0, 0 ,-size + y*cellSize + cellSize/2.0);
				drawCheckerStack(cell->player,cell->nCheckers);
				glPopMatrix();
			}

	glPushMatrix();
	glTranslatef(0, 0 ,white_board_z);
	drawCheckerStack(WHITE,white_board_ncheckers);
	glPopMatrix();

	glPushMatrix();
	glTranslatef(0, 0 ,black_board_z);
	drawCheckerStack(BLACK,black_board_ncheckers);
	glPopMatrix();
}

void Board::drawSelected(GLenum mode, bool visible){
	float xi,xf,zi,zf;

	if (mode == GL_SELECT)
		glPushName(0);

	for(unsigned int i = 0; i < selected.size(); ++i){
		xi = -size + selected[i].first*cellSize;
		xf = xi + cellSize;

		zi = -size + selected[i].second*cellSize;
		zf = zi + cellSize;

		if(mode == GL_SELECT){
			glLoadName(selected[i].first*100 +selected[i].second);

			if(selected[i].first > -1 && selected[i].first < 8 && selected[i].second > -1 && selected[i].second <8 )
				if(cells[selected[i].second][selected[i].first].nCheckers > 0){
					glPushMatrix();
					glTranslatef(-size + selected[i].first*cellSize + cellSize/2.0, 0 ,-size + selected[i].second*cellSize + cellSize/2.0);
					drawCheckerStack(cells[selected[i].second][selected[i].first].player,cells[selected[i].second][selected[i].first].nCheckers);
					glPopMatrix();
				}
		}

		if(mode == GL_SELECT || visible){
			selected_material.applyMaterial();
			glBegin(GL_POLYGON);
				glNormal3f(0,1,0);
				glVertex3f(xi,0.01,zi);
				glVertex3f(xi,0.01,zf);
				glVertex3f(xf,0.01,zf);
				glVertex3f(xf,0.01,zi);
			glEnd();
		}
	}

	if (mode == GL_SELECT)
		glPopName();
}

void Board::draw(GLenum mode,float xy_aspect, float* obj_pos, float* view_rotate){

	setCamera(xy_aspect, obj_pos, view_rotate);
	
	drawBoard(mode);

	if(game_status == CHECKER_CHOICE)
		drawSelected(mode,false);
	else if(game_status == MOVE_CHOICE)
		drawSelected(mode,true);
}

void Board::initializeAnimation(Move move){
	if(application_status == GAME){
		GameState gs;
		memcpy(gs.cells,cells,64*sizeof(BoardCell));
		gs.move = move;
		gs.white_n_checkers = white_n_checkers;
		gs.black_n_checkers = black_n_checkers;
		states.push_back(gs);

		timer_on = false;
	}

	animation.move = move;

	animation.xi = -size + move.xi*cellSize + cellSize/2.0;
	animation.zi = -size + move.yi*cellSize + cellSize/2.0;
	animation.xf = -size + move.xf*cellSize + cellSize/2.0;
	animation.zf = -size + move.yf*cellSize + cellSize/2.0;

	if(move.xi >-1 && move.xi <8 && move.yi >-1 && move.yi<8){
		animation.yi = (cells[move.yi][move.xi].nCheckers -= move.n_checkers)*checkerHeight;
		if(cells[move.yi][move.xi].nCheckers == 0)
			cells[move.yi][move.xi].player=NONE;
	}
	else
		animation.yi = 0;

	if(move.xf >-1 && move.xf <8 && move.yf >-1 && move.yf<8)
		animation.yf = cells[move.yf][move.xf].player == move.player? cells[move.yf][move.xf].nCheckers*checkerHeight : 0;
	else
		animation.yf = 0;

	animation.delta_y = v*delta_t/1000.0;

	animation.move_x = move.xi == move.xf ? 0 : 1;
	animation.move_z = move.yi == move.yf ? 0 : 1;

	int x_signal = move.xi > move.xf ? -1 : 1;
	int z_signal = move.yi > move.yf ? -1 : 1;

	if(animation.move_x && !animation.move_z)
		animation.delta_x = x_signal*v*delta_t/1000.0;
	else if(animation.move_z && !animation.move_x)
		animation.delta_z = z_signal*v*delta_t/1000.0;
	else{
		float ang = atan((animation.zf-animation.zi)/(animation.xf-animation.xi));
		animation.delta_x = v*cos(ang)*delta_t/1000.0;
		animation.delta_z = v*sin(ang)*delta_t/1000.0;

		if((animation.delta_x > 0 && x_signal == -1) || (animation.delta_x < 0 && x_signal == 1))
			animation.delta_x *= -1;
		if((animation.delta_z > 0 && z_signal == -1) || (animation.delta_z < 0 && z_signal == 1))
			animation.delta_z *= -1;
	}

	if(move.moveType == CAPTURE){
		captured_animation.player = cells[move.yf][move.xf].player;
		captured_animation.n_checkers = cells[move.yf][move.xf].nCheckers;
		captured_animation.x = animation.xf;
		captured_animation.z = animation.zf;

		int captured_signal = captured_animation.player == WHITE ? 1 : -1;
		captured_animation.zf = animation.zf + captured_signal*cellSize;
		captured_animation.delta_z = captured_signal*v*delta_t/4000.0;

		captured_animation_status = CAPTURED_BACK;

		cells[move.yf][move.xf].player = NONE;
		cells[move.yf][move.xf].nCheckers = 0;
	}

	if(move.moveType == REMOVE || move.moveType == CAPTURE){
		remove_animation.player = move.moveType == REMOVE ? move.player : captured_animation.player;
		remove_animation.n_checkers = move.moveType == REMOVE ? move.n_checkers : captured_animation.n_checkers;

		remove_animation.x = move.moveType == REMOVE ? animation.xf : captured_animation.x;
		remove_animation.y = 0;
		remove_animation.z = move.moveType == REMOVE ? animation.zf : captured_animation.zf;
		
		remove_animation.xf = 0;
		switch(remove_animation.player){
		case WHITE:
			remove_animation.yf = white_board_ncheckers * checkerHeight;
			remove_animation.zf = white_board_z;
			break;
		case BLACK:
			remove_animation.yf = black_board_ncheckers * checkerHeight;
			remove_animation.zf = black_board_z;
			break;
		}

		remove_animation.delta_y = v*delta_t/1000.0;

		remove_animation.move_x = remove_animation.x == 0 ? 0 : 1;
		remove_animation.move_z = 1;

		int remove_x_signal = remove_animation.x > remove_animation.xf ? -1 : 1;
		int remove_z_signal = remove_animation.z > remove_animation.zf ? -1 : 1;

		if(!remove_animation.move_x)
			remove_animation.delta_z = remove_z_signal*v*delta_t/1000.0;
		else{
			float ang = atan((remove_animation.zf-remove_animation.z)/(remove_animation.xf-remove_animation.x));
			remove_animation.delta_x = v*cos(ang)*delta_t/1000.0;
			remove_animation.delta_z = v*sin(ang)*delta_t/1000.0;

			if((remove_animation.delta_x > 0 && remove_x_signal == -1) || (remove_animation.delta_x < 0 && remove_x_signal == 1))
				remove_animation.delta_x *= -1;
			if((remove_animation.delta_z > 0 && remove_z_signal == -1) || (remove_animation.delta_z < 0 && remove_z_signal == 1))
				remove_animation.delta_z *= -1;
		}
		remove_animation_status = REMOVE_UP;
	}

	game_status = ANIMATION;
	ani_status = UP;
}

void Board::drawAnimation(){
	if(ani_status != WAIT_REMOVE){
		glPushMatrix();
		glTranslatef(animation.xi,animation.yi,animation.zi);
		drawCheckerStack(animation.move.player,animation.move.n_checkers);
		glPopMatrix();
	}
	if(captured_animation_status != CAPTURED_NO_MORE){
		glPushMatrix();
		glTranslatef(captured_animation.x,0,captured_animation.z);
		drawCheckerStack(captured_animation.player,captured_animation.n_checkers);
		glPopMatrix();
	}
	if(ani_status == WAIT_REMOVE || ani_status == WAIT_CAPTURE){
		glPushMatrix();
		glTranslatef(remove_animation.x,remove_animation.y,remove_animation.z);
		drawCheckerStack(remove_animation.player,remove_animation.n_checkers);
		glPopMatrix();
	}
}

void Board::finalizeMove(){
	switch(animation.move.moveType){
		case MERGE:
			cells[animation.move.yf][animation.move.xf].nCheckers += animation.move.n_checkers;
			break;
		case CAPTURE:
			if(animation.move.player == WHITE){
				black_n_checkers -= captured_animation.n_checkers;
				black_board_ncheckers = 12 - black_n_checkers;
			}
			else if(animation.move.player == BLACK){
				white_n_checkers -= captured_animation.n_checkers;
				white_board_ncheckers = 12 - white_n_checkers;
			}
			cells[animation.move.yf][animation.move.xf].nCheckers = animation.move.n_checkers;
			cells[animation.move.yf][animation.move.xf].player = animation.move.player;
			break;
		case NORMAL:
			cells[animation.move.yf][animation.move.xf].nCheckers = animation.move.n_checkers;
			cells[animation.move.yf][animation.move.xf].player = animation.move.player;
			break;
		case REMOVE:
			if(animation.move.player == WHITE){
				white_n_checkers -= animation.move.n_checkers;
				white_board_ncheckers = 12 - white_n_checkers;
			}
			else if(animation.move.player == BLACK){
				black_n_checkers -= animation.move.n_checkers;
				black_board_ncheckers = 12 - black_n_checkers;
			}
			break;
	}

	if(application_status == GAME){
		if(white_n_checkers == 0){
			application_status = END_GAME;
			game_status = HOLD;
			quit();
		}
		else if(black_n_checkers == 0){
			application_status = END_GAME;
			game_status = HOLD;
			quit();
		}
		else{
			changeTurn();
		}
	}
	else if(application_status == GAME_FILM){
		++game_film_turn;
		if(game_film_turn == states.size()){
			application_status = END_GAME;
			game_status = HOLD;
		}
		else{
			initializeAnimation(states[game_film_turn].move);
		}
	}
}

void Board::undo(){
	if(application_status == GAME){
		if(states.empty())
			return;

		GameState gs = states.back();

		while(gs.move.player == WHITE && white_player == COMP || gs.move.player == BLACK && black_player == COMP){
			states.pop_back();
			if(states.empty())
				return;
			gs = states.back();
		}

		memcpy(cells,gs.cells, 64*sizeof(BoardCell));
		white_n_checkers = gs.white_n_checkers;
		black_n_checkers = gs.black_n_checkers;
		white_board_ncheckers = 12 - white_n_checkers;
		black_board_ncheckers = 12 - black_n_checkers;
		turn = gs.move.player;

		states.pop_back();

		if(getCurrentPlayerControl() == HUMAN){
			game_status = CHECKER_CHOICE;

			selected.clear();
			selected = getPlayerPositions(toString(), turn);
			initializeTimer();
		}
		else
			game_status = COMP_CHOICE;
	}
}

void Board::initializeGameFilm(){
	game_film_turn = 0;
	GameState gs = states[0];

	memcpy(cells,gs.cells, 64*sizeof(BoardCell));
	white_n_checkers = gs.white_n_checkers;
	black_n_checkers = gs.black_n_checkers;
	turn = gs.move.player;

	white_board_ncheckers = 0;
	black_board_ncheckers = 0;

	initializeAnimation(gs.move);
}

void Board::changeTurn(){
	turn = turn == WHITE ? BLACK : WHITE;
	if(getCurrentPlayerControl() == HUMAN){
		game_status = CHECKER_CHOICE;

		selected.clear();
		selected = getPlayerPositions(toString(), turn);
		initializeTimer();
	}
	else
		game_status = COMP_CHOICE;
}

void Board::initializeTimer(){
	if(timer){
		current_time = getCurrentTime();
		end_time = current_time + maximum_time;
		timer_on = true;
	}
}

void Board::setCamera(float xy_aspect, float* obj_pos, float* view_rotate){
	glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 500.0 );

	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	
	switch(current_cam){
	case FREE:
		glTranslated(0.0,0.0,-30.0);
		glRotated(45.0, 1.0,0.0,0.0 );
		glTranslatef( obj_pos[0], obj_pos[1], -obj_pos[2] ); 
		glMultMatrixf( view_rotate );
		break;
	case W:
		camera_white.setCamera();
		break;
	case B:
		camera_black.setCamera();
		break;
	case BW:
		camera_black_white.setCamera();
		break;
	case WB:
		camera_white_black.setCamera();
		break;
	}
	if(ani_camera_status == ANIMATE)
		glRotated(ani_camera.current_ang,0,1,0);
}

void Board::initializeCameraAnimation(Cam final_cam){
	ani_camera.final_cam = final_cam;
	ani_camera.ti = getCurrentTime();
	ani_camera.current_ang = 0;
	switch(current_cam){
		case W:
			switch(final_cam){
				case B:
					ani_camera.ang = 180;
					ani_camera.tf = ani_camera.ti + 2000;
					break;
				case BW:
					ani_camera.ang = 90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
				case WB:
					ani_camera.ang = -90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
			}
			break;
		case B:
			switch(final_cam){
				case W:
					ani_camera.ang = 180;
					ani_camera.tf = ani_camera.ti + 2000;
					break;
				case WB:
					ani_camera.ang = 90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
				case BW:
					ani_camera.ang = -90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
			}
			break;
		case BW:
			switch(final_cam){
				case WB:
					ani_camera.ang = 180;
					ani_camera.tf = ani_camera.ti + 2000;
					break;
				case B:
					ani_camera.ang = 90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
				case W:
					ani_camera.ang = -90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
			}
			break;
		case WB:
			switch(final_cam){
				case BW:
					ani_camera.ang = 180;
					ani_camera.tf = ani_camera.ti + 2000;
					break;
				case W:
					ani_camera.ang = 90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
				case B:
					ani_camera.ang = -90;
					ani_camera.tf = ani_camera.ti + 1000;
					break;
			}
			break;
	}
	ani_camera.tf_minus_ti = ani_camera.tf - ani_camera.ti;
	ani_camera_status = ANIMATE;
}

void Board::write_string(char* s, int length){
	for(int i = 0; i < length; ++i )
		glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, s[i]);
}

void Board::showText(int window_w, int window_h){
	glDisable(GL_LIGHTING);
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0,window_w,0,window_h);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	glColor3f(1.0,1.0,0.0);
	glRasterPos3f(10,window_h-30,0);
	
	write_string("White: ", 7);
	char pont[3];
	itoa(white_n_checkers,pont,10);
	write_string(pont,strlen(pont));

	glRasterPos3f(10,window_h-60,0);
	write_string("Black: ", 7);
	itoa(black_n_checkers,pont,10);
	write_string(pont,strlen(pont));

	if(application_status == GAME){
		glRasterPos3f(10,window_h-90,0);
		write_string("Turno: ", 7);
		if(turn == WHITE)
			write_string("White",5);
		else if(turn == BLACK)
			write_string("Black",5);
	}

	if(timer && timer_on){
		int time_left = (end_time - current_time) / 1000 + 1;
		char s_time_left[3];
		itoa(time_left,s_time_left,10);
		glRasterPos3f(10,window_h-120,0);
		write_string("Tempo restante: ", 16);
		write_string(s_time_left,strlen(s_time_left));
	}
	
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glEnable(GL_LIGHTING);
}

void Board::updateAnimation(){
	if(game_status == ANIMATION){
		if(captured_animation_status == CAPTURED_BACK){
			if(captured_animation.delta_z > 0 && captured_animation.z < captured_animation.zf ||
				captured_animation.delta_z < 0 && captured_animation.z > captured_animation.zf)
				captured_animation.z += captured_animation.delta_z;
			else
				captured_animation_status = CAPTURED_WAIT;
		}

		switch(ani_status){
			case UP:
				if(animation.yi < 12*checkerHeight)
					animation.yi += animation.delta_y;
				else
					ani_status = MOVE;
				break;
			case MOVE:
				if(animation.move_x || animation.move_z){
					if(animation.move_x){
						if(animation.delta_x > 0){
							if(animation.xi < animation.xf){
								animation.xi += animation.delta_x;
								if(animation.xi >= animation.xf)
									animation.move_x = 0;
							}
						}
						else{
							if(animation.xi > animation.xf){
								animation.xi += animation.delta_x;
								if(animation.xi <= animation.xf)
									animation.move_x = 0;
							}
						}
					}
					if(animation.move_z){
						if(animation.delta_z > 0){
							if(animation.zi < animation.zf){
								animation.zi += animation.delta_z;
								if(animation.zi >= animation.zf)
									animation.move_z = 0;
							}
						}
						else{
							if(animation.zi > animation.zf){
								animation.zi += animation.delta_z;
								if(animation.zi <= animation.zf)
									animation.move_z = 0;
							}
						}
					}
				}
				else
					ani_status = DOWN;
				break;
			case DOWN:
				if(animation.yi > animation.yf)
					animation.yi -= animation.delta_y;
				else if(animation.move.moveType == CAPTURE){
					ani_status = WAIT_CAPTURE;
					captured_animation_status = CAPTURED_NO_MORE;
				}
				else if(animation.move.moveType == REMOVE){
					ani_status = WAIT_REMOVE;
				}
				else{
					finalizeMove();
				}
				break;
			case WAIT_REMOVE:
			case WAIT_CAPTURE:
				updateRemoveAnimation();
				break;
		}
	}
	if(timer && timer_on){
		current_time = getCurrentTime() ;
		if(current_time >= end_time){
			timer_on = false;
			changeTurn();
		}
	}
}

void Board::updateRemoveAnimation(){
	switch(remove_animation_status){
	case REMOVE_UP:
		if(remove_animation.y < 12*checkerHeight)
			remove_animation.y += remove_animation.delta_y;
		else
			remove_animation_status = REMOVE_MOVE;
		break;
	case REMOVE_MOVE:
		if(remove_animation.move_x || remove_animation.move_z){
			if(remove_animation.move_x){
				if(remove_animation.delta_x > 0){
					if(remove_animation.x < remove_animation.xf){
						remove_animation.x += remove_animation.delta_x;
						if(remove_animation.x >= remove_animation.xf)
							remove_animation.move_x = 0;
					}
				}
				else{
					if(remove_animation.x > remove_animation.xf){
						remove_animation.x += remove_animation.delta_x;
						if(remove_animation.x <= remove_animation.xf)
							remove_animation.move_x = 0;
					}
				}
			}
			if(remove_animation.move_z){
				if(remove_animation.delta_z > 0){
					if(remove_animation.z < remove_animation.zf){
						remove_animation.z += remove_animation.delta_z;
						if(remove_animation.z >= remove_animation.zf)
							remove_animation.move_z = 0;
					}
				}
				else{
					if(remove_animation.z > remove_animation.zf){
						remove_animation.z += remove_animation.delta_z;
						if(remove_animation.z <= remove_animation.zf)
							remove_animation.move_z = 0;
					}
				}
			}
		}
		else
			remove_animation_status = REMOVE_DOWN;
		break;
	case REMOVE_DOWN:
		if(remove_animation.y > remove_animation.yf)
			remove_animation.y -= remove_animation.delta_y;
		else{
			finalizeMove();
		}
		break;
	}
}